/*
 * FnThread2.c
 * Created on December 4, 2007; 3:27 PM
 * by VRamadurai
 */

/************ System Header Files ***************/
#include <stdio.h>
#include <stdlib.h>

/************ Private Header Files **************/
#include "HsTypes.h"
#include "PhyDebug.h"
#include "PhyStruct.h"
#include "PmdGlobals.h"
#include "PhyConstants.h"
#include "tables.h"
#include "iqdma_3500.h"
#include "rx_functions.h"
#include "training.h"
#include "correlation.h"
#include "sync_correlation.h"
#include "sfd_header.h"
#include "rx1_functions.h"
#include "rx2_functions.h"
#include "rx55_functions.h"
#include "rx11_functions.h"
#include "equalizer.h"
#include "thread_globals.h"
//#include "FnThread22.h"
#include "threads_common.h"//add 627

/*format ssSineTable A(0,15)*/
extern hs_int16_t ssCosineSineTable[513*2] ;

hs_int16_t w_LEri[32];
hs_int16_t buff_LEri[2*(N_LE+RXSIZE)];

#define VEC_LEN (16)

hs_int32_t cck_55_new_rpu_asm(	hs_int16_t *eqOutI,
								hs_int16_t *usAbsCorr,
            					hs_int16_t *ssRxSymbI,
								hs_int16_t *ssRxSymbQ,
								hs_int16_t *psHalfRateCckSeq
							);

#define SB_INLINE   inline

static inline
void cck_opt_total(short * in, short * twid, int * out_index,
                  int * max_index, short * maxI, short * maxQ, short * out_iq,
                  short *in_mask)
{
    short in_rev[VEC_LEN];
    short temp[VEC_LEN];
    short temp0[VEC_LEN], temp1[VEC_LEN];
    short temp_a[VEC_LEN], temp_b[VEC_LEN], temp_pow[VEC_LEN];
    int max = 0, count = 0, pos = 0;
    short * twida = twid;
    short * twidb = twid + 48;

    __sb_rmul(in, in, in_mask);
    /* reverse the input */
    __sb_rrev(in_rev,in);

    __sb_rfft0s(temp,in_rev,twida);

    __sb_rfft1s(temp0,temp,twida+VEC_LEN);
    __sb_rfft1s(temp1,temp,twidb+VEC_LEN);

    __sb_rfft2s(out_iq + 0*VEC_LEN,temp0,twida+2*VEC_LEN);
    __sb_rfft2s(out_iq + 1*VEC_LEN,temp0,twidb+2*VEC_LEN);

    __sb_rmuls(temp_a,out_iq + 0*VEC_LEN,out_iq + 0*VEC_LEN);
    __sb_rmuls(temp_b,out_iq + 1*VEC_LEN,out_iq + 1*VEC_LEN);

    __sb_rmsumjs_0(temp_pow, 0, temp_a, temp_b);
    __sb_rsearchmax(&max,&count,&pos,max,count,pos,temp_pow);

    __sb_rfft2s(out_iq + 2*VEC_LEN,temp1,twida+2*VEC_LEN);
    __sb_rfft2s(out_iq + 3*VEC_LEN,temp1,twidb+2*VEC_LEN);

    __sb_rmuls(temp_a,out_iq + 2*VEC_LEN,out_iq + 2*VEC_LEN);
    __sb_rmuls(temp_b,out_iq + 3*VEC_LEN,out_iq + 3*VEC_LEN);
    __sb_rmsumjs_0(temp_pow, 0, temp_a, temp_b);
    __sb_rsearchmax(&max,&count,&pos,max,count,pos,temp_pow);
    __sb_rfft0s(temp,in_rev,twidb);

    __sb_rfft1s(temp0,temp,twida+VEC_LEN);
    __sb_rfft1s(temp1,temp,twidb+VEC_LEN);

    __sb_rfft2s(out_iq + 4*VEC_LEN,temp0,twida+2*VEC_LEN);
    __sb_rfft2s(out_iq + 5*VEC_LEN,temp0,twidb+2*VEC_LEN);

    __sb_rmuls(temp_a,out_iq + 4*VEC_LEN,out_iq + 4*VEC_LEN);
    __sb_rmuls(temp_b,out_iq + 5*VEC_LEN,out_iq + 5*VEC_LEN);
    __sb_rmsumjs_0(temp_pow, 0, temp_a, temp_b);
    __sb_rsearchmax(&max,&count,&pos,max,count,pos,temp_pow);

    __sb_rfft2s(out_iq + 6*VEC_LEN,temp1,twida+2*VEC_LEN);
    __sb_rfft2s(out_iq + 7*VEC_LEN,temp1,twidb+2*VEC_LEN);

    __sb_rmuls(temp_a,out_iq + 6*VEC_LEN,out_iq + 6*VEC_LEN);
    __sb_rmuls(temp_b,out_iq + 7*VEC_LEN,out_iq + 7*VEC_LEN);
    __sb_rmsumjs_0(temp_pow, 0, temp_a, temp_b);
    __sb_rsearchmax(&max,&count,&pos,max,count,pos,temp_pow);

    *maxI = out_iq[2*pos + 1];
    *maxQ = out_iq[2*pos + 0];
    *max_index = out_index[pos];
}

SB_INLINE
void symbol_lock_th2(
                        struct HS_Phy11bStr  *HS_Phy11bPtrTh,
                        hs_int16_t *preamble_buffI,
                        hs_int16_t *preamble_buffQ,
                        hs_int16_t *psSampBarkerSeq,
                        volatile hs_int32_t *thread2to3_flag1_ptr,
                        volatile hs_int32_t *thread1to2_flag1_ptr
                    )
{
    #define NUM_LOCK_SYMBOLS 4

    hs_int16_t ssRxSymbI;
    hs_int16_t ssRxSymbQ;
    hs_int32_t siAccumI;
    hs_int32_t siAccumQ;

    hs_int32_t k;
    //hs_int32_t i;
    hs_int32_t symcount;

    /** Update sincos table **/
    while(thread1to2_sincos_flag == 0){
    	SPIN(8);
    }
    thread1to2_sincos_flag = 0;

    get_sin_cos_values(HS_Phy11bPtrTh, ssCosineSineTable);

    thread2to1_sincos_flag = 1;

    /** Collect symbols **/
    k = 0;
    while(1)
    {
        /** sync with thread1 **/
        while(*thread1to2_flag1_ptr == 0){
        	SPIN(128);
        }

        START_CLOCK

        for(symcount=0; symcount<NUM_LOCK_SYMBOLS; symcount++){
            siAccumI = 0;
            siAccumQ = 0;
            ssRxSymbI = __sb_rmulred(siAccumI, psSampBarkerSeq, &preamble_buffI[k*11]);
            ssRxSymbQ = __sb_rmulred(siAccumQ, psSampBarkerSeq, &preamble_buffQ[k*11]);

            HS_Phy11bPtrTh->ssRxSymbOldI = ssRxSymbI;
            HS_Phy11bPtrTh->ssRxSymbOldQ = ssRxSymbQ;

            k++;
            if(k == PREAMBLE_SYNC_SYMBOLS)
            {
                /** Signal thread3 for symbol lock/preamble-sync **/
                *thread2to3_flag1_ptr = 1;
                break;
            }
        }

        /** signal back to thread1 **/
        *thread1to2_flag1_ptr = 0;

        if(k == PREAMBLE_SYNC_SYMBOLS)
        {
            break;
        }
    }

    PRINT_CYCLES("symbol lock 2");
}

SB_INLINE
void wlan_eq_pre_th2(
                        struct HS_Phy11bStr  *HS_Phy11bPtrTh,
                        hs_int16_t *w_LEri,
                        hs_int16_t *buff_LEri,
                        hs_int16_t *RefEq,
                        hs_int16_t *outIBase
                    )
{
	hs_int16_t refeq[16];
	hs_int16_t shift[16];
    hs_int16_t *ssOutI;
    hs_int16_t *ssOutQ;

    hs_int32_t count;
    hs_int32_t outbuff_toggle;
    hs_int32_t energy;
    hs_int32_t eq_in_index;

    __sb_rbroad(shift, EQ_REF_SCALE<<16, 0);

    /** sync with thread1 **/
    while(thread1to2_flag1 == 0){
        __sb_barrier();
    }

    START_CLOCK

    energy = HS_Phy11bPtrTh->eq_energy;

    outbuff_toggle = HS_Phy11bPtrTh->outbuff_toggle_th2;

    ssOutI = outIBase + outbuff_toggle*OUTBUFFSIZE*2;
    ssOutQ = ssOutI + OUTBUFFSIZE;

    HS_Phy11bPtrTh->outbuff_toggle_th2 ^= 1;

    /** Wait for thread3 to update the eq index **/
    while(thread3_eq_index_flag == 0){
        __sb_barrier();
    }
    //PRINT_CYCLES("eq_pre 2");
    eq_in_index = HS_Phy11bPtrTh->eq_in_index;

    __sb_rshf(&buff_LEri[2*(N_PRE+N_POST)], &buff_LEri[2*(N_PRE+N_POST)+16], ssOutI, ssOutQ, 7);
    __sb_rshra(refeq, &RefEq[eq_in_index], shift);
    count = AdaptiveEqPreamble_7_asm(buff_LEri, w_LEri, refeq, energy, HS_Phy11bPtrTh->eq_count);

    HS_Phy11bPtrTh->eq_count = count;

    PRINT_CYCLES("eq_pre 2");

    /** signal back to thread1 **/
    thread1to2_flag1 = 0;
}

SB_INLINE
void
wlan_sfd_th2(
                struct HS_Phy11bStr  *HS_Phy11bPtrTh,
                hs_int16_t *w_LEri,
                hs_int16_t *buff_LEri,
                hs_int16_t *RefEq,
                hs_int16_t *outIBase,
                volatile hs_int32_t *thread2to3_flag1_ptr,
                volatile hs_int32_t *thread1to2_flag1_ptr
             )
{
	#define NUM_SFD_SYMBOLS	4

	hs_int16_t refeq[16];
	hs_int16_t shift[16];

    hs_int16_t *ssOutI;
    hs_int16_t *ssOutQ;

    hs_int32_t rem_count;
    hs_int32_t count;
    hs_int32_t outbuff_toggle;
    hs_int32_t eq_in_index;
    hs_int32_t energy;
    hs_int32_t symcount;

    count = HS_Phy11bPtrTh->eq_count;
    eq_in_index = HS_Phy11bPtrTh->eq_in_index + N_PRE;
    energy = HS_Phy11bPtrTh->eq_energy;

    outbuff_toggle = HS_Phy11bPtrTh->outbuff_toggle_th2;
    rem_count = PREAMBLE_DOWNSAMPLE_REFSIZE - eq_in_index;

    __sb_rbroad(shift, EQ_REF_SCALE<<16, 0);

    /** sync with thread3 **/
    while(*thread2to3_flag1_ptr == 1){
        __sb_barrier();
    }

    *thread2to3_flag1_ptr = 1;

    while(1)
    {
        /** sync with thread1 **/
        while(*thread1to2_flag1_ptr == 0){
            __sb_barrier();
        }

        START_CLOCK

        ssOutI = outIBase + OUTBUFFSIZE*2*outbuff_toggle;
        ssOutQ = ssOutI + OUTBUFFSIZE;
        outbuff_toggle ^= 1;

        if(rem_count >= 44){
	        for(symcount=0; symcount<NUM_SFD_SYMBOLS; symcount++)
	        {
	            __sb_rshf(&buff_LEri[2*(N_PRE+N_POST)], &buff_LEri[2*(N_PRE+N_POST)+16],
	                ssOutI+symcount*11, ssOutQ+symcount*11, 7);

	            __sb_rshra(refeq, &RefEq[eq_in_index], shift);

	            count = AdaptiveEqPreamble_11_4_asm(buff_LEri, w_LEri, refeq, energy, count);

	            eq_in_index += 11;
	        }
	        rem_count -= 4*11;
        }
        else{
        	__sb_rshf(&buff_LEri[2*(N_PRE+N_POST)], &buff_LEri[2*(N_PRE+N_POST)+16],
        		                ssOutI, ssOutQ, 7);

            __sb_rshra(refeq, &RefEq[eq_in_index], shift);

            count = AdaptiveEqPreamble_11_4_asm(buff_LEri, w_LEri, refeq, energy, count);

            eq_in_index += 11;
            rem_count -= 11;
        }


        /** signal back to thread1 **/
        *thread1to2_flag1_ptr = 0;

        if(eq_in_index >= PREAMBLE_DOWNSAMPLE_REFSIZE){
            break;
        }
    }

    PRINT_CYCLES("sfd detection 2");

    HS_Phy11bPtrTh->eq_count = count;
    HS_Phy11bPtrTh->outbuff_toggle_th2 = outbuff_toggle;
}

SB_INLINE
void
wlan_header_th2(
                struct HS_Phy11bStr  *HS_Phy11bPtrTh,
                hs_int16_t *w_LEri,
                hs_int16_t *buff_LEri,
                hs_int16_t *outIBase,
                hs_int16_t *eqOutIQBase,
                volatile hs_int32_t *thread2to3_flag1_ptr,
                volatile hs_int32_t *thread1to2_flag1_ptr
             )
{
    #define NUM_HEAD_SYMBOLS 4

    hs_int16_t *ssOutI;
    hs_int16_t *ssOutQ;
    hs_int16_t *eqOutI;
    hs_int16_t *eqOutQ;

    hs_int32_t outbuff_toggle;
    hs_int32_t eqoutbuff_toggle;
    hs_int32_t symbol_count;
    hs_int32_t count;
    hs_int16_t eq_output[32];

    outbuff_toggle = HS_Phy11bPtrTh->outbuff_toggle_th2;
    eqoutbuff_toggle = HS_Phy11bPtrTh->eqoutbuff_toggle_th2;

    symbol_count = 0;
    while(1)
    {
        /** sync with thread1 **/
        while(*thread1to2_flag1_ptr == 0){
            __sb_barrier();
        }

        START_CLOCK

        ssOutI = outIBase + OUTBUFFSIZE*2*outbuff_toggle;
        ssOutQ = ssOutI + OUTBUFFSIZE;
        outbuff_toggle ^= 1;

        eqOutI = eqOutIQBase + EQOUTBUFFSIZE*2*eqoutbuff_toggle;
        eqOutQ = eqOutI + EQOUTBUFFSIZE;
        eqoutbuff_toggle ^= 1;

        for(count=0; count<NUM_HEAD_SYMBOLS; count++){

            __sb_rshf(&buff_LEri[2*(N_PRE+N_POST)], &buff_LEri[2*(N_PRE+N_POST)+16],
                ssOutI+count*11, ssOutQ+count*11, 7);

            AdaptiveEqData_11_asm(buff_LEri, w_LEri, eq_output);

            __sb_rshf1(eqOutI+count*11, eqOutQ+count*11, eq_output, eq_output+16, 7);

        }

        /** sync with thread3 **/
        while(*thread2to3_flag1_ptr == 1){
            __sb_barrier();
        }

        *thread2to3_flag1_ptr = 1;

        symbol_count += NUM_HEAD_SYMBOLS;
        if(symbol_count == N_HEADER_SYMB){
            break;
        }

        /** signal back to thread1 **/
        *thread1to2_flag1_ptr = 0;
    }

    PRINT_CYCLES("header detection 2");

    HS_Phy11bPtrTh->outbuff_toggle_th2 = outbuff_toggle;
    HS_Phy11bPtrTh->eqoutbuff_toggle_th2 = eqoutbuff_toggle;

    /** signal back to thread1 **/
    *thread1to2_flag1_ptr = 0;
}

SB_INLINE
void
wlan_data12_th2(
                struct HS_Phy11bStr  *HS_Phy11bPtrTh,
                hs_int16_t *w_LEri,
                hs_int16_t *buff_LEri,
                hs_int16_t *outIBase,
                hs_int16_t *eqOutIQBase,
                volatile hs_int32_t *thread2to3_flag1_ptr,
                volatile hs_int32_t *thread1to2_flag1_ptr
             )
{
    #define NUM_DATA12_SYMBOLS 4

    hs_int16_t *ssOutI;
    hs_int16_t *ssOutQ;
    hs_int16_t *eqOutI;
    hs_int16_t *eqOutQ;

    hs_int32_t outbuff_toggle;
    hs_int32_t eqoutbuff_toggle;
    hs_int32_t symbol_count;
    hs_int32_t count;
    hs_int16_t eq_output[32];

    hs_int32_t siNPayloadSym = HS_Phy11bPtrTh->siNPayloadSym;

    outbuff_toggle = HS_Phy11bPtrTh->outbuff_toggle_th2;
    eqoutbuff_toggle = HS_Phy11bPtrTh->eqoutbuff_toggle_th2;

    symbol_count = 0;

    while(thread3toall_rate_flag == 0){
		__sb_barrier();
    }

    if(*HS_Phy11bPtrTh->rx_status_l == HS_HEAD_CRC_ERROR){
    	return;
    }

    while(1)
    {
        /** sync with thread1 **/
        while(*thread1to2_flag1_ptr == 0){
            __sb_barrier();
        }

        START_CLOCK

        ssOutI = outIBase + OUTBUFFSIZE*2*outbuff_toggle;
        ssOutQ = ssOutI + OUTBUFFSIZE;
        outbuff_toggle ^= 1;

        eqOutI = eqOutIQBase + EQOUTBUFFSIZE*2*eqoutbuff_toggle;
        eqOutQ = eqOutI + EQOUTBUFFSIZE;
        eqoutbuff_toggle ^= 1;

        for(count=0; count<NUM_DATA12_SYMBOLS; count++){

            __sb_rshf(&buff_LEri[2*(N_PRE+N_POST)], &buff_LEri[2*(N_PRE+N_POST)+16],
                ssOutI+count*11, ssOutQ+count*11, 7);

            AdaptiveEqData_11_asm(buff_LEri, w_LEri, eq_output);

            __sb_rshf1(eqOutI+count*11, eqOutQ+count*11, eq_output, eq_output+16, 7);

        }

        /** sync with thread3 **/
        while(*thread2to3_flag1_ptr == 1){
            __sb_barrier();
        }

        *thread2to3_flag1_ptr = 1;

        /** signal back to thread1 **/
        *thread1to2_flag1_ptr = 0;

        symbol_count += NUM_DATA12_SYMBOLS;
        if(symbol_count == siNPayloadSym){
            break;
        }
    }

    PRINT_CYCLES("data 12mbps 2");
}

SB_INLINE
void wlan_data11_th2(
                        struct HS_Phy11bStr  *HS_Phy11bPtrTh,
                        hs_uint8_t  *puc11MbpsByteTranslate,
                        hs_int32_t  *unscrambled_index,
                        hs_int16_t  *twiddle_stage012_total,
                        hs_int16_t  *eq_output,
						hs_int16_t  *ssRxSymbIQ,
                        hs_uint8_t  *ucCckBits,
                        hs_int16_t  *eqOutIQBase,
                        volatile hs_int32_t *thread1to2_flag1_ptr,
                        volatile hs_int32_t *thread2to3_flag1_ptr
                    )
{
    #define NUM_DATA11_SYMBOLS 2

	hs_int16_t in_mask[16] = {4,-4,4,-4,4,-4,-4,4,4,-4,4,-4,-4,4,4,-4};

    hs_int32_t max_index[2];
    hs_int32_t siNPayloadSym = HS_Phy11bPtrTh->siNPayloadSym;

	hs_int16_t ssRxI[2];
	hs_int16_t ssRxQ[2];
    hs_int16_t *eqOutI;
    hs_int32_t eqoutbuff_toggle;
    hs_int32_t i;
    hs_int32_t cck_toggle;

    hs_int32_t siTempNSymCount = 0;

    cck_toggle = HS_Phy11bPtrTh->cck_toggle_th2;
    eqoutbuff_toggle = HS_Phy11bPtrTh->eqoutbuff_toggle_th3;

    while(thread3toall_rate_flag == 0){
		__sb_barrier();
    }

    if(*HS_Phy11bPtrTh->rx_status_l == HS_HEAD_CRC_ERROR){
    	return;
    }

    while(1)
    {
        /** sync with thread2 **/
        while(*thread1to2_flag1_ptr == 0){
            __sb_barrier();
        }

        START_CLOCK_11

        eqOutI = eqOutIQBase + EQOUTBUFFSIZE*2*eqoutbuff_toggle;
        eqoutbuff_toggle ^= 1;

        for(i=0; i<NUM_DATA11_SYMBOLS; i++){
	        cck_opt_total(
	            eqOutI+i*16,
	            twiddle_stage012_total,
	            unscrambled_index,
	            &max_index[i],
				&ssRxI[i],
				&ssRxQ[i],
	            eq_output,
	            in_mask
	        );
        }

        for(i=0; i<NUM_DATA11_SYMBOLS; i++){
            ucCckBits[cck_toggle*2+i] = puc11MbpsByteTranslate[max_index[i]];
			ssRxSymbIQ[4*cck_toggle+2*i+0] = ssRxI[i] >> 3;
			ssRxSymbIQ[4*cck_toggle+2*i+1] = (-ssRxQ[i]) >> 3;
        }

        /** Signal back to thread1 **/
		*thread1to2_flag1_ptr = 0;

        /** sync with thread3 **/
        while(*thread2to3_flag1_ptr == 1){
            __sb_barrier();
        }

        *thread2to3_flag1_ptr = 1;

        cck_toggle ^= 1;

        siTempNSymCount+=2;

        if(siTempNSymCount >= siNPayloadSym)
        {
            break;
        }
    }

    PRINT_CYCLES_11("data 11mbps 2");
}

SB_INLINE
void wlan_data55_th2(
                        struct HS_Phy11bStr  *HS_Phy11bPtrTh,
                        hs_int16_t  *psHalfRateCckSeq,
                        hs_uint8_t  *u8_byte_translate_array,
                        hs_int16_t  *eqOutIQBase,
                        hs_uint8_t  *ucCckBits,
                        hs_int16_t  *ssRxSymbIQ,
                        volatile hs_int32_t *thread1to2_flag1_ptr,
                        volatile hs_int32_t *thread2to3_flag1_ptr
                    )
{
    #define NUM_55_SYMBOLS 2

	hs_int16_t eq_temp[64];

    hs_int32_t eqoutbuff_toggle;
    hs_int32_t cck_toggle;
    hs_int16_t usAbsCorr[16];
    hs_int32_t offset;

    hs_int16_t *eqOutI;

    hs_int32_t siTempNSymCount = 0;
    hs_int32_t siNPayloadSym = HS_Phy11bPtrTh->siNPayloadSym;

    eqoutbuff_toggle = HS_Phy11bPtrTh->eqoutbuff_toggle_th3;
    cck_toggle = HS_Phy11bPtrTh->cck_toggle_th2;

    while(thread3toall_rate_flag == 0){
		__sb_barrier();
    }

    if(*HS_Phy11bPtrTh->rx_status_l == HS_HEAD_CRC_ERROR){
    	return;
    }

    while(1)
    {
        /** sync with thread2 **/
        while(*thread1to2_flag1_ptr == 0){
            __sb_barrier();
        }

        START_CLOCK_55

        eqOutI = eqOutIQBase + EQOUTBUFFSIZE*2*eqoutbuff_toggle;
        eqoutbuff_toggle ^= 1;

        __sb_rshf1(eq_temp, eq_temp+16, eqOutI, eqOutI+16, 3);
        __sb_rshf1(eq_temp+16, eq_temp+32, eqOutI+16, eqOutI+32, 3);


        /** CCK **/
        offset = cck_55_new_rpu_asm(eq_temp, usAbsCorr,
            		&ssRxSymbIQ[4*cck_toggle+0], &ssRxSymbIQ[4*cck_toggle+1], psHalfRateCckSeq);

    	ucCckBits[2*cck_toggle+0] = u8_byte_translate_array[offset];

    	offset = cck_55_new_rpu_asm(eq_temp+16, usAbsCorr,
            		&ssRxSymbIQ[4*cck_toggle+2+0], &ssRxSymbIQ[4*cck_toggle+2+1], psHalfRateCckSeq);

    	ucCckBits[2*cck_toggle+1] = u8_byte_translate_array[offset];


        /** Signal back to thread2 **/
        *thread1to2_flag1_ptr = 0;

        /** sync with thread4 **/
	    while(*thread2to3_flag1_ptr == 1){
	        __sb_barrier();
	    }

	    *thread2to3_flag1_ptr = 1;

	    cck_toggle ^= 1;

        siTempNSymCount += 2;
        if(siTempNSymCount >= siNPayloadSym)
        {
            break;
        }
    }

    PRINT_CYCLES_55("data 5.5mbps 2");
}

void*
FnThread2(void *t)
{
	hs_int32_t mode;
    hs_int32_t i;
    hs_int32_t ePhyState;
    hs_int16_t twiddle_stage012_total[16*3*2];
    hs_int16_t 	eq_output[8*16];
    hs_int16_t *outIBase;
    hs_int16_t *eqOutIQBase;
    hs_int16_t *eqOutIQBase_11;

    hs_uint8_t  u8_byte_translate_array[4] = {0,2,1,3};
    hs_int16_t  HalfRateCckSeq[64+16];

    hs_int32_t unscrambled_index[64] = {
        0,52,12,56,3,55,15,59,
        2,54,14,58,1,53,13,57,
        4,48,8,60,7,51,11,63,
        6,50,10,62,5,49,9,61,
        32,20,44,24,35,23,47,27,
        34,22,46,26,33,21,45,25,
        36,16,40,28,39,19,43,31,
        38,18,42,30,37,17,41,29
    };

    hs_uint8_t ucTranslate_array_rpu[64] = {
       0, 32, 48, 16, 8, 40, 56, 24,
       12, 44, 60, 28, 4, 36, 52, 20,
       2, 34, 50, 18, 10, 42, 58, 26,
       14, 46, 62, 30, 6, 38, 54, 22,
       3, 35, 51, 19, 11, 43, 59, 27,
       15, 47, 63, 31, 7, 39, 55, 23,
       1, 33, 49, 17, 9, 41, 57, 25,
       13, 45, 61, 29, 5, 37, 53, 21
    };

    hs_int16_t psSampBarkerSeq[16] =
    {
        1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 0, 0, 0, 0, 0
    };

    volatile hs_int32_t *thread2to3_flag1_ptr = &thread2to3_flag1;
    volatile hs_int32_t *thread1to2_flag1_ptr = &thread1to2_flag1;

    struct HS_Phy11bStr  *HS_Phy11bPtrTh2 = &HS_Phy11bPtrGlobal;

    hs_int16_t *preamble_buffI = HS_Phy11bPtrTh2->preamble_buffI;
    hs_int16_t *preamble_buffQ = HS_Phy11bPtrTh2->preamble_buffQ;

    /** Interleave I/Q and change sign of Q **/
    for(i=0; i<32; i++){
        HalfRateCckSeq[2*i+0] = HalfRateCckSeq_g[i]<<2;
        HalfRateCckSeq[2*i+1] = -HalfRateCckSeq_g[32+i]<<2;
    }

    for(i=0; i<16*3*2; i++){
        twiddle_stage012_total[i] = twiddle_stage012_total_g[i];
    }



    while(threads_all_init_done == 0){
    	__sb_barrier();
    }



    outIBase = ssOutIQ_shared;
    eqOutIQBase = eqOutIQ_shared;
    eqOutIQBase_11 = eqOutIQ_shared_11;

    while(1)
    {
BEGIN_LOOP2:



		while(tx_rx_mode_2 == 0){
			__sb_barrier();
		}

	    mode = tx_rx_mode_2;

	    tx_rx_mode_2 = 0;


	    if(mode == TX_MODE){
	    	FnThread22(NULL);
	    }
	    else if(mode == RX_MODE){

	    	/** wait until energy is detected in Thread 1 **/
	    	while(HS_Phy11bPtrTh2->e_detected == 0)
	    	{
	    		SPIN(32);
	    	}
	    	if(HS_Phy11bPtrTh2->e_detected < 0){
	    		goto BEGIN_LOOP2;
	    	}

	    	ePhyState = PHY_RX_SYMBOL_LOCK_TH;

		    while(ePhyState != PHY_STATE_SWITCH_OFF_TH)
		    {
		        switch(ePhyState)
		        {
		            case PHY_STATE_SWITCH_OFF_TH:
		            {
		                break;
		            }

		            case PHY_RX_SYMBOL_LOCK_TH:
		            {
		            	//printf("test file %s, line %d\n",__FILE__,__LINE__);
		            	AdaptiveEqTapsInit(w_LEri);
		        	    AdaptiveEqInit(HS_Phy11bPtrTh2, buff_LEri);
		                symbol_lock_th2(HS_Phy11bPtrTh2, preamble_buffI, preamble_buffQ, psSampBarkerSeq, thread2to3_flag1_ptr, thread1to2_flag1_ptr);
		                ePhyState  = PHY_RX_STATE_SFD_TH;
		                break;
		            }

		            case PHY_RX_STATE_SFD_TH:
		            {
		            	//printf("test file %s, line %d\n",__FILE__,__LINE__);
		                wlan_eq_pre_th2(HS_Phy11bPtrTh2, w_LEri, buff_LEri, eq_pream_sfd_ref, outIBase);
		                wlan_sfd_th2(HS_Phy11bPtrTh2, w_LEri, buff_LEri, eq_pream_sfd_ref, outIBase, thread2to3_flag1_ptr, thread1to2_flag1_ptr);
		                ePhyState  = PHY_RX_STATE_HEADER_TH;
		                break;
		            }

		            case PHY_RX_STATE_HEADER_TH:
		            {
		            	//printf("test file %s, line %d\n",__FILE__,__LINE__);
		                wlan_header_th2(HS_Phy11bPtrTh2, w_LEri, buff_LEri, outIBase, eqOutIQBase, thread2to3_flag1_ptr, thread1to2_flag1_ptr);

		                ePhyState  = HS_Phy11bPtrTh2->ePhyState;
		                break;
		            }

		            case PHY_STATE_DM_ONEMBPS_TH:
		            {
		                wlan_data12_th2(HS_Phy11bPtrTh2, w_LEri, buff_LEri, outIBase, eqOutIQBase, thread2to3_flag1_ptr, thread1to2_flag1_ptr);
		                ePhyState  = PHY_STATE_SWITCH_OFF_TH;
		                break;
		            }

		            case PHY_STATE_DM_TWOMBPS_TH:
		            {
		                wlan_data12_th2(HS_Phy11bPtrTh2, w_LEri, buff_LEri, outIBase, eqOutIQBase, thread2to3_flag1_ptr, thread1to2_flag1_ptr);
		                ePhyState  = PHY_STATE_SWITCH_OFF_TH;
		                break;
		            }

		            case PHY_STATE_DM_FIVEDOTFIVE_TH:
		            {
		            	wlan_data55_th2(HS_Phy11bPtrTh2, HalfRateCckSeq, u8_byte_translate_array,
			                			eqOutIQBase_11, ucCckBits_shared, ssRxSymbIQ_shared, thread1to2_flag1_ptr,
			                		    thread2to3_flag1_ptr);

		                ePhyState  = PHY_STATE_SWITCH_OFF_TH;
		                break;
		            }

		            case PHY_STATE_DM_ELEVENMBPS_TH:
		            {
		            	wlan_data11_th2(HS_Phy11bPtrTh2, ucTranslate_array_rpu, unscrambled_index,
		                                twiddle_stage012_total, eq_output, ssRxSymbIQ_shared, ucCckBits_shared,
		                                eqOutIQBase_11, thread1to2_flag1_ptr, thread2to3_flag1_ptr);

		                ePhyState  = PHY_STATE_SWITCH_OFF_TH;
		                break;
		            }
		        }
		    }
	    }
    }
}
